package com.creator.pangu.core.security.service;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.lang.UUID;
import com.creator.pangu.common.dto.LoginBody;
import com.creator.pangu.common.exception.CaptchaException;
import com.creator.pangu.common.exception.CaptchaExpireException;
import com.creator.pangu.core.security.dto.LoginUser;
import com.creator.pangu.core.security.util.JWTUtil;
import com.creator.pangu.core.security.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class LoginService {

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private JWTUtil jwtUtil;

    @Resource
    private RedisUtil redisUtil;

    @Value("${captcha.width}")
    private int width;

    @Value("${captcha.height}")
    private int height;

    @Value("${captcha.code-count}")
    private int codeCount;

    @Value("${captcha.line-count}")
    private int lineCount;

    @Value("${captcha.expire-time}")
    private long expireTime;


    /**
     * 处理登录逻辑
     *
     * @param loginBody
     * @return
     */
    public String login(LoginBody loginBody) {

        // 验证码校验
        validateCaptcha(loginBody.getCode(), loginBody.getUuid());

        // 用户名和密码验证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        Authentication authentication = authenticationManager.authenticate(authenticationToken);

        //获取验证成功的对象信息
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();

        //存入缓存
        redisUtil.setCacheObject(loginUser.getUsername(), loginUser);
        //签发token
        return jwtUtil.sign(loginUser.getUsername());
    }

    /**
     * 验证码校验
     *
     * @param code 页面提交验证码
     * @param uuid 缓存验证码唯一标识
     */
    public void validateCaptcha(String code, String uuid) {
        //缓存中取出captcha
        String captcha = redisUtil.getCacheObject(uuid);
        //删除缓存中captcha
        redisUtil.deleteObject(uuid);
        if (captcha == null) {
            //验证码过期
            log.error("验证码过期！");
            throw new CaptchaExpireException();
        }
        if (!code.equalsIgnoreCase(captcha)) {
            log.error("验证码错误！");
            throw new CaptchaException();
        }
    }

    public Map<String, Object> createCaptcha() {

        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(width, height, codeCount, lineCount);

        lineCaptcha.createCode();

        // 定义验证码唯一字符串
        String codeUUID = UUID.fastUUID().toString();
        log.info("验证码生成成功值为：{}，验证码唯一标志为：{}", lineCaptcha.getCode(), codeUUID);
        // 放入缓存中
        redisUtil.setCacheObject(codeUUID, lineCaptcha.getCode(), expireTime, TimeUnit.MINUTES);
        // 返回前端对象
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("img", lineCaptcha.getImageBase64Data());
        result.put("uuid", codeUUID);

        return result;
    }

}
